include(FeatureSummary)

function(qdoc_add_qch target_name)
    set(options LOG_QUITE)
    set(oneValueArgs NAME DOC_NAME VERSION NAMESPACE QCH_INSTALL_DESTINATION TAGFILE_INSTALL_DESTINATION CONFIG_TEMPLATE)
    set(multiValueArgs SOURCES SOURCE_DIRS HEADERS HEADER_DIRS INCLUDE_DIRS IMAGES IMAGE_DIRS EXAMPLES EXAMPLE_DIRS EXCLUDE_FILES EXCLUDE_DIRS DEPEND_QCHS)
    cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})


    #---------------------------------------------------------
    # 检查必要参数
    #---------------------------------------------------------
    foreach (arg_name NAME DOC_NAME VERSION QCH_INSTALL_DESTINATION)
        if(NOT DEFINED ARGS_${arg_name})
            message(FATAL_ERROR "${arg_name} needs to be defined when calling qdoc_add_qch")
        endif()
    endforeach ()

    if(NOT DEFINED ARGS_SOURCE_DIRS AND NOT DEFINED ARGS_SOURCES)
        message(FATAL_ERROR "SOURCE_DIRS or SOURCES needs to be defined when calling qdoc_add_qch")
    endif()

    if(NOT DEFINED ARGS_HEADER_DIRS AND NOT DEFINED ARGS_HEADERS)
        message(FATAL_ERROR "HEADER_DIRS or HEADERS needs to be defined when calling qdoc_add_qch")
    endif()

    #---------------------------------------------------------
    # 查找qdoc qhelpgenerator 工具
    #---------------------------------------------------------
    if (${QT_VERSION_MAJOR} EQUAL "5")
        find_program(QDoc_EXECUTABLE NAMES qdoc qdoc-qt5)
        set_package_properties(QDoc_EXECUTABLE PROPERTIES
                TYPE REQUIRED
                PURPOSE "Needed for API dox QCH file generation"
                DESCRIPTION "Part of Qt5 tools"
        )
        find_program(QHelpGenerator_EXECUTABLE NAMES qhelpgenerator qhelpgenerator-qt5)
        set_package_properties(QHelpGenerator_EXECUTABLE PROPERTIES
                TYPE REQUIRED
                PURPOSE "Needed for API dox QCH file generation"
                DESCRIPTION "Part of Qt5 tools"
        )

        message(STATUS "QDoc_EXECUTABLE: ${QDoc_EXECUTABLE}")
        message(STATUS "QHelpGenerator_EXECUTABLE: ${QHelpGenerator_EXECUTABLE}")

    else()
        find_package(Qt6 COMPONENTS ToolsTools CONFIG REQUIRED)
        set_package_properties(Qt6ToolsTools PROPERTIES
                TYPE REQUIRED
                PURPOSE "Needed for API dox QCH file generation"
                DESCRIPTION "qhelpgenerator from Qt6 tools"
        )
        if(TARGET Qt6::qdoc)
            get_target_property(QDoc_EXECUTABLE Qt6::qdoc LOCATION)
        endif()
        if(TARGET Qt6::qhelpgenerator)
            get_target_property(QHelpGenerator_EXECUTABLE Qt6::qhelpgenerator LOCATION)
        endif()
    endif()

    set(missing_tools)
    if (NOT QDoc_EXECUTABLE AND NOT TARGET Qt6::qdoc)
        list(APPEND missing_tools "qdoc")
    endif()
    if (NOT QHelpGenerator_EXECUTABLE AND NOT TARGET Qt6::qhelpgenerator)
        list(APPEND missing_tools "qhelpgenerator")
    endif()

    if (missing_tools)
        message(WARNING "API dox QCH file will not be generated, tools missing: ${missing_tools}!")
    else()
        #---------------------------------------------------------
        # 配置模板文件参数
        #---------------------------------------------------------

        if (DEFINED ARGS_DOC_NAME)
            set(doc_name ${ARGS_DOC_NAME})
        else()
            set(doc_name ${ARGS_NAME})
        endif()

        set(output_dir "${CMAKE_CURRENT_BINARY_DIR}/doc")
        set(QDOC_OUTPUT_DIR "${output_dir}")

        set(QDOC_PROJECT_NAME "${ARGS_NAME}")
        set(QDOC_NAME "${doc_name}")

        set(QDOC_PROJECT_VERSION ${ARGS_VERSION})
        set(QDOC_NAMESPACE ${ARGS_NAMESPACE})
        #qch 安装路径
        set(qch_install_destination ${ARGS_QCH_INSTALL_DESTINATION})
        #tagfile 安装路径
        if (DEFINED ARGS_TAGFILE_INSTALL_DESTINATION)
            set(tagfile_install_destination ${ARGS_TAGFILE_INSTALL_DESTINATION})
        else ()
            set(tagfile_install_destination "${qch_install_destination}/${doc_name}")
        endif ()

        #tags
        set(qdoc_output_tags_file "${output_dir}/${doc_name}.tags")
        set(QDOC_TAGS_FILE "${qdoc_output_tags_file}")

        if (DEFINED ARGS_CONFIG_TEMPLATE)
            set(qdoc_config_template_file ${ARGS_CONFIG_TEMPLATE})
        else()
            set(qdoc_config_template_file "${CMAKE_CURRENT_SOURCE_DIR}/QDocConfig.qdocconf.in")
        endif()

        set(qdoc_config_file "${CMAKE_CURRENT_BINARY_DIR}/${doc_name}.qdocconf")

        #sources source_dirs
        set(QDOC_SOURCE_DIRS)
        foreach(source_dir IN LISTS ARGS_SOURCE_DIRS)
            if (NOT IS_ABSOLUTE ${source_dir})
                set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}/${source_dir}")
            endif()
            set(QDOC_SOURCE_DIRS "${QDOC_SOURCE_DIRS} \\\n\"${source_dir}\"")
        endforeach()

        set(QDOC_SOURCES)
        foreach(source IN LISTS ARGS_SOURCES)
            if (NOT IS_ABSOLUTE ${source})
                set(source "${CMAKE_CURRENT_SOURCE_DIR}/${source}")
            endif()
            list(APPEND sources "${source}")
        endforeach()
        foreach(source IN LISTS sources)
            set(QDOC_SOURCES "${QDOC_SOURCES} \\\n\"${source}\"")
        endforeach()

        #headers header_dirs
        set(QDOC_HEADER_DIRS)
        foreach(header_dir IN LISTS ARGS_HEADER_DIRS)
            if (NOT IS_ABSOLUTE ${header_dir})
                set(header_dir "${CMAKE_CURRENT_SOURCE_DIR}/${header_dir}")
            endif()
            set(QDOC_HEADER_DIRS "${QDOC_HEADER_DIRS} \\\n\"${header_dir}\"")
        endforeach()

        set(QDOC_HEADERS)
        foreach(header IN LISTS ARGS_HEADERS)
            if (NOT IS_ABSOLUTE ${header})
                set(header "${CMAKE_CURRENT_SOURCE_DIR}/${header}")
            endif()
            list(APPEND headers "${header}")
        endforeach()
        foreach(header IN LISTS headers)
            set(QDOC_HEADERS "${QDOC_HEADERS} \\\n\"${header}\"")
        endforeach()

        #include_dirs
        set(QDOC_INCLUDE_DIRS)
        foreach(include_dir IN LISTS ARGS_INCLUDE_DIRS)
            if (NOT IS_ABSOLUTE ${include_dir})
                set(include_dir "${CMAKE_CURRENT_SOURCE_DIR}/${include_dir}")
            endif()
            set(QDOC_INCLUDE_DIRS "${QDOC_INCLUDE_DIRS} \\\n\"${include_dir}\"")
        endforeach()

        #images
        set(QDOC_IMAGE_DIRS)
        foreach(image_dir IN LISTS ARGS_IMAGE_DIRS)
            if (NOT IS_ABSOLUTE ${image_dir})
                set(image_dir "${CMAKE_CURRENT_SOURCE_DIR}/${image_dir}")
            endif()
            set(QDOC_IMAGE_DIRS "${QDOC_IMAGE_DIRS} \\\n\"${image_dir}\"")
        endforeach()

        set(QDOC_IMAGES)
        foreach(image IN LISTS ARGS_IMAGES)
            if (NOT IS_ABSOLUTE ${image})
                set(image "${CMAKE_CURRENT_SOURCE_DIR}/${image}")
            endif()
            list(APPEND images "${image}")
        endforeach()
        foreach(image IN LISTS images)
            set(QDOC_IMAGES "${QDOC_IMAGES} \\\n\"${image}\"")
        endforeach()

        #example_dirs examples 示例目录
        set(QDOC_EXAMPLE_DIRS)
        foreach(example_dir IN LISTS ARGS_EXAMPLE_DIRS)
            if (NOT IS_ABSOLUTE ${example_dir})
                set(example_dir "${CMAKE_CURRENT_SOURCE_DIR}/${example_dir}")
            endif()
            set(QDOC_EXAMPLE_DIRS "${QDOC_EXAMPLE_DIRS} \\\n\"${example_dir}\"")
        endforeach()

        set(QDOC_EXAMPLES)
        foreach(example IN LISTS ARGS_EXAMPLES)
            if (NOT IS_ABSOLUTE ${example})
                set(example "${CMAKE_CURRENT_SOURCE_DIR}/${example}")
            endif()
            list(APPEND examples "${example}")
        endforeach()
        foreach(example IN LISTS examples)
            set(QDOC_EXAMPLES "${QDOC_EXAMPLES} \\\n\"${example}\"")
        endforeach()

        #exclude_files exclude_dirs 需要排除的文件
        set(QDOC_EXCLUDE_DIRS)
        foreach(exclude_dir IN LISTS ARGS_EXCLUDE_DIRS)
            if (NOT IS_ABSOLUTE ${exclude_dir})
                set(exclude_dir "${CMAKE_CURRENT_SOURCE_DIR}/${exclude_dir}")
            endif()
            set(QDOC_EXCLUDE_DIRS "${QDOC_EXCLUDE_DIRS} \\\n\"${exclude_dir}\"")
        endforeach()

        set(QDOC_EXCLUDE_FILES)
        foreach(exclude_file IN LISTS ARGS_EXCLUDE_FILES)
            if (NOT IS_ABSOLUTE ${exclude_file})
                set(exclude_file "${CMAKE_CURRENT_SOURCE_DIR}/${exclude_file}")
            endif()
            list(APPEND exclude_files "${exclude_file}")
        endforeach()
        foreach(exclude_file IN LISTS exclude_files)
            set(QDOC_EXCLUDE_FILES "${QDOC_EXCLUDE_FILES} \\\n\"${exclude_file}\"")
        endforeach()

        #depends_qchs
        set(QDOC_DEPEND_QCHS)
        foreach(depend_qch IN LISTS ARGS_DEPEND_QCHS)
            if (NOT IS_ABSOLUTE ${depend_qch})
                set(depend_qch "${CMAKE_CURRENT_SOURCE_DIR}/${depend_qch}")
            endif()
            list(APPEND depend_qchs "${depend_qch}")
        endforeach()
        foreach(depend_qch IN LISTS depend_qchs)
            set(QDOC_DEPEND_QCHS "${QDOC_DEPEND_QCHS} \\\n\"${depend_qch}\"")
        endforeach()
        #----------------------------------
        # finally create qdoc config file
        configure_file(
                "${qdoc_config_template_file}"
                "${qdoc_config_file}"
                @ONLY
        )

        set(qdoc_output_qhp_file "${output_dir}/${doc_name}.qhp")
        set(qdoc_output_qch_file "${output_dir}/${doc_name}.qch")

        #日志暂未处理，后续默认输出日志到文件， 开启开关输出日志到终端
        set(custom_command_log_file "${CMAKE_CURRENT_BINARY_DIR}/${doc_name}.log")

        add_custom_command(
                OUTPUT ${qdoc_output_qhp_file} ${qdoc_output_qch_file}
                COMMENT "Generating ${_relative_qch_file}, ${_relative_tags_file}"
                COMMAND cmake -E remove_directory "${output_dir}"
                COMMAND cmake -E make_directory "${output_dir}"
                COMMAND ${QDoc_EXECUTABLE} "${qdoc_config_file}"
                COMMAND ${QHelpGenerator_EXECUTABLE} "${qdoc_output_qhp_file}" -o "${qdoc_output_qch_file}"
                DEPENDS
                ${qdoc_config_file}
                ${depend_qchs}
        )
        add_custom_target(${target_name} ALL DEPENDS ${qdoc_output_qhp_file} ${qdoc_output_qch_file})
        # setup installation
        install(FILES
                ${qdoc_output_qch_file}
                DESTINATION ${qch_install_destination}
        )

        install(FILES
                ${qdoc_output_tags_file}
                DESTINATION ${tagfile_install_destination}
        )

    endif ()
endfunction()